//
//  AlbumNativePickerViewController.swift
//  Media
//
//  Created by han on 2021/6/8.
//

import UIKit
import PhotosUI
import Photos
import MobileCoreServices

class AlbumNativePickerViewController: UIViewController {

    @IBOutlet weak var livePhotoView: PHLivePhotoView!
    @IBOutlet weak var imageView: UIImageView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    @IBAction func callPHPickerAction(_ sender: Any) {
        callPHPicker()
    }
    
    @IBAction func callImagePickerAction(_ sender: Any) {
        callImagePicker()
    }
    
    @IBAction func saveAction(_ sender: Any) {
        if self.imageView.image != nil {
            saveImage(imageView.image!)
        }
        if self.livePhotoView.livePhoto != nil {
           // self.livePhotoView.livePhoto
            
        }
    }
    
    @IBAction func takePicker(_ sender: Any) {
        takePictureImagePicker()
    }
    
    private var itemProviders = [NSItemProvider]()
    private var itemProvidersIterator: IndexingIterator<[NSItemProvider]>?
    private var currentItemProvider: NSItemProvider?
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)
        displayNextImage()
    }
    
    func saveImage(_ image: UIImage) {
        PHPhotoLibrary.shared().performChanges({
            PHAssetChangeRequest.creationRequestForAsset(from: image)
        }, completionHandler: {success, error in
            showTips(self, "保存结果", success ? "保存成功" : "保存失败")
            if !success { print("error creating asset: \(String(describing: error))") }
        })
    }
}

// MARK: ImagePicker
extension AlbumNativePickerViewController {
    // 调用相册选择
    func callImagePicker() {
        // 不支持多选
        let imagePicker = UIImagePickerController()
        imagePicker.delegate = self
        imagePicker.allowsEditing = true
        guard self.checkPhoto() else { return }
        imagePicker.sourceType = .photoLibrary
        imagePicker.mediaTypes = [ kUTTypeMovie as String, kUTTypeImage as String]
        self.present(imagePicker, animated: true, completion: nil)
    }
    
    // 拍照
    func takePictureImagePicker() {
        let imagePicker = UIImagePickerController()
        imagePicker.delegate = self
        imagePicker.allowsEditing = true
        guard self.checkCamera() else { return }
        imagePicker.sourceType = .camera
        self.present(imagePicker, animated: true, completion: nil)
    }
    
    // 相册权限
    func checkPhoto() -> Bool {
        let status =  PHPhotoLibrary.authorizationStatus()
        if status == .denied || status == .restricted {
            showTips(self, "", "请在iPhone的“设置->隐私->照片”中打开本应用的访问权限")
            return false
        }
        return true
    }
    
    // 拍照权限
    func checkCamera() -> Bool {
        guard UIImagePickerController.isSourceTypeAvailable(.camera) else {
            showTips(self, "", "该设备不支持拍照")
            return false
        }
        let status = AVCaptureDevice.authorizationStatus(for: .video)
        if status == .denied || status == .restricted {
            showTips(self, "", "请在iPhone的“设置->隐私->相机”中打开本应用的访问权限")
            return false
        }
        return true
    }
    
    // 常用调用系统相册功能
    func customCallImagePicker() {
        let imagePicker = UIImagePickerController()
        imagePicker.delegate = self
        imagePicker.allowsEditing = true
        let alert = UIAlertController(title: "调用原生", message: "", preferredStyle: .actionSheet)
        alert.addAction(UIAlertAction(title: "相册", style: .default, handler: { action in
            guard self.checkPhoto() else { return }
            imagePicker.sourceType = .photoLibrary
            imagePicker.mediaTypes = [ kUTTypeMovie as String, kUTTypeImage as String]
            self.present(imagePicker, animated: true, completion: nil)
        }))
        alert.addAction(UIAlertAction(title: "相机", style: .default, handler: { action in
            guard  self.checkCamera() else { return }
            imagePicker.sourceType = .camera
            self.present(imagePicker, animated: true, completion: nil)
        }))
        alert.addAction(UIAlertAction(title: "取消", style: .cancel, handler: nil))
        present(alert, animated: true, completion: nil)
    }
}

extension AlbumNativePickerViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        picker.dismiss(animated: true) {
            guard let editedImage: UIImage = info[.editedImage] as? UIImage else {
                return
            }
            self.imageView.image = editedImage
            if picker.sourceType == .camera {
                // 保存一下原图
                let  originalImage: UIImage  = info[.originalImage] as! UIImage
                UIImageWriteToSavedPhotosAlbum(originalImage, self, nil, nil)
            }
        }
    }
    
    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        picker.dismiss(animated: true, completion: nil)
    }
}

// MARK: PHPicker
extension AlbumNativePickerViewController {
    func callPHPicker(filter: PHPickerFilter? = nil) {
        var configuration = PHPickerConfiguration()
        configuration.filter = filter // 也可以不设置
        configuration.selectionLimit = 0 // 允许选多少个，0表示不做限制
        let picker = PHPickerViewController(configuration: configuration)
        picker.delegate = self
        
        present(picker, animated: true)
    }
    
    func displayNextImage() {
        guard let itemProvider = itemProvidersIterator?.next() else { return }
        currentItemProvider = itemProvider
        if itemProvider.canLoadObject(ofClass: PHLivePhoto.self) {
            itemProvider.loadObject(ofClass: PHLivePhoto.self) { [weak self] livePhoto, error in
                DispatchQueue.main.async {
                    guard let self = self, self.currentItemProvider == itemProvider else { return }
                    if let livePhoto = livePhoto as? PHLivePhoto {
                        self.display(livePhoto: livePhoto)
                        self.livePhotoView.startPlayback(with: .full)
                    } else {
                        self.display(image: UIImage(systemName: "exclamationmark.circle"))
                        showTips(self, "", "Couldn't load LivePhoto with error: \(error?.localizedDescription ?? "unknown error")")
                    }
                }
            }
        } else if itemProvider.canLoadObject(ofClass: UIImage.self) {
            itemProvider.loadObject(ofClass: UIImage.self) { [weak self] image, error in
                DispatchQueue.main.async {
                    guard let self = self, self.currentItemProvider == itemProvider else { return }
                    if let image = image as? UIImage {
                        self.display(image: image)
                    } else {
                        self.display(image: UIImage(systemName: "exclamationmark.circle"))
                        showTips(self, "", "Couldn't load image with error: \(error?.localizedDescription ?? "unknown error")")
                    }
                }
            }
        } else {
            showTips(self, "", "Unsupported item provider: \(itemProvider)")
        }
    }
    
    func display(livePhoto: PHLivePhoto? = nil, image: UIImage? = nil) {
        livePhotoView.livePhoto = livePhoto
        livePhotoView.isHidden = livePhoto == nil
        imageView.image = image
        imageView.isHidden = image == nil
    }
}

extension AlbumNativePickerViewController: PHPickerViewControllerDelegate {
    func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
        dismiss(animated: true)
        itemProviders = results.map(\.itemProvider)
        itemProvidersIterator = itemProviders.makeIterator()
        displayNextImage()
    }
}


// MARK: Tools
func showTips(_ viewController: UIViewController, _ title: String, _ message: String?) {
    let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
    alert.addAction(UIAlertAction(title: "确定", style: .cancel, handler: nil))
    viewController.present(alert, animated: true, completion: nil)
}
